Latviešu

Atklājiet GraphQL federācijas jaudu, izmantojot shēmu savienošanu. Uzziniet, kā izveidot vienotu GraphQL API no vairākiem servisiem, uzlabojot mērogojamību un uzturēšanu.

GraphQL federācija: Shēmu savienošana (Schema Stitching) - Visaptverošs ceļvedis

Pastāvīgi mainīgajā moderno lietojumprogrammu izstrādes ainavā nepieciešamība pēc mērogojamas un uzturamas arhitektūras ir kļuvusi par galveno prioritāti. Mikroservisi ar tiem raksturīgo modularitāti un neatkarīgo izvietojamību ir kļuvuši par populāru risinājumu. Tomēr daudzu mikropakalpojumu pārvaldība var radīt sarežģījumus, jo īpaši, ja runa ir par vienotas API nodrošināšanu klienta lietojumprogrammām. Šeit savu lomu spēlē GraphQL federācija un īpaši shēmu savienošana (Schema Stitching).

Kas ir GraphQL federācija?

GraphQL federācija ir jaudīga arhitektūra, kas ļauj jums izveidot vienotu GraphQL API no vairākiem pamatā esošiem GraphQL servisiem (kas bieži pārstāv mikroservisus). Tā ļauj izstrādātājiem vaicāt datus no dažādiem servisiem tā, it kā tie būtu viens grafs, vienkāršojot klienta pieredzi un samazinot nepieciešamību pēc sarežģītas orķestrēšanas loģikas klienta pusē.

GraphQL federācijai ir divas galvenās pieejas:

Šis raksts ir veltīts shēmu savienošanai, pētot tās koncepcijas, priekšrocības, ierobežojumus un praktisko ieviešanu.

Izpratne par shēmu savienošanu

Shēmu savienošana ir vairāku GraphQL shēmu apvienošanas process vienā, saskaņotā shēmā. Šī vienotā shēma darbojas kā fasāde, slēpjot no klienta pamatā esošo servisu sarežģītību. Kad klients veic pieprasījumu uz savienoto shēmu, vārteja gudri novirza pieprasījumu uz attiecīgo(-ajiem) pamatā esošo(-ajiem) servisu(-iem), iegūst datus un apvieno rezultātus, pirms tos atgriež klientam.

Iedomājieties to šādi: jums ir vairāki restorāni (servisi), kas katrs specializējas dažādās virtuvēs. Shēmu savienošana ir kā universāla ēdienkarte, kas apvieno visus ēdienus no katra restorāna. Kad klients (klients) pasūta no universālās ēdienkartes, pasūtījums tiek gudri novirzīts uz attiecīgajām restorānu virtuvēm, ēdiens tiek pagatavots un pēc tam apvienots vienā piegādē klientam.

Shēmu savienošanas pamatjēdzieni

Shēmu savienošanas priekšrocības

Shēmu savienošana piedāvā vairākas pārliecinošas priekšrocības organizācijām, kas pieņem mikroservisu arhitektūru:

Shēmu savienošanas ierobežojumi

Lai gan shēmu savienošana piedāvā daudzas priekšrocības, ir svarīgi apzināties tās ierobežojumus:

Shēmu savienošanas praktiskā ieviešana

Apskatīsim vienkāršotu piemēru, kā ieviest shēmu savienošanu, izmantojot Node.js un graphql-tools bibliotēku (populāra izvēle shēmu savienošanai). Šis piemērs ietver divus mikroservisus: Lietotāju servisu un Produktu servisu.

1. Definējiet attālinātās shēmas

Vispirms definējiet GraphQL shēmas katram no attālinātajiem servisiem.

Lietotāju serviss (user-service.js):


const { buildSchema } = require('graphql');

const userSchema = buildSchema(`
  type User {
    id: ID!
    name: String
    email: String
  }

  type Query {
    user(id: ID!): User
  }
`);

const users = [
  { id: '1', name: 'Alice Smith', email: 'alice@example.com' },
  { id: '2', name: 'Bob Johnson', email: 'bob@example.com' },
];

const userRoot = {
  user: (args) => users.find(user => user.id === args.id),
};

module.exports = {
  schema: userSchema,
  rootValue: userRoot,
};

Produktu serviss (product-service.js):


const { buildSchema } = require('graphql');

const productSchema = buildSchema(`
  type Product {
    id: ID!
    name: String
    price: Float
    userId: ID!  # Ārējā atslēga uz Lietotāju servisu
  }

  type Query {
    product(id: ID!): Product
  }
`);

const products = [
  { id: '101', name: 'Laptop', price: 1200, userId: '1' },
  { id: '102', name: 'Smartphone', price: 800, userId: '2' },
];

const productRoot = {
  product: (args) => products.find(product => product.id === args.id),
};

module.exports = {
  schema: productSchema,
  rootValue: productRoot,
};

2. Izveidojiet vārtejas servisu

Tagad izveidojiet vārtejas servisu, kas savienos abas shēmas kopā.

Vārtejas serviss (gateway.js):


const { stitchSchemas } = require('@graphql-tools/stitch');
const { makeRemoteExecutableSchema } = require('@graphql-tools/wrap');
const { graphqlHTTP } = require('express-graphql');
const express = require('express');
const { introspectSchema } = require('@graphql-tools/wrap');
const { printSchema } = require('graphql');
const fetch = require('node-fetch');

async function createRemoteSchema(uri) {
  const fetcher = async (params) => {
    const response = await fetch(uri, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(params),
    });
    return response.json();
  };

  const schema = await introspectSchema(fetcher);
  return makeRemoteExecutableSchema({
    schema,
    fetcher,
  });
}

async function main() {
  const userSchema = await createRemoteSchema('http://localhost:4001/graphql');
  const productSchema = await createRemoteSchema('http://localhost:4002/graphql');

  const stitchedSchema = stitchSchemas({
    subschemas: [
      { schema: userSchema },
      { schema: productSchema },
    ],
    typeDefs: `
      extend type Product {
        user: User
      }
    `,
    resolvers: {
      Product: {
        user: {
          selectionSet: `{ userId }`,
          resolve(product, args, context, info) {
            return info.mergeInfo.delegateToSchema({
              schema: userSchema,
              operation: 'query',
              fieldName: 'user',
              args: {
                id: product.userId,
              },
              context,
              info,
            });
          },
        },
      },
    },
  });

  const app = express();
  app.use('/graphql', graphqlHTTP({
    schema: stitchedSchema,
    graphiql: true,
  }));

  app.listen(4000, () => console.log('Vārtejas serveris darbojas http://localhost:4000/graphql'));
}

main().catch(console.error);

3. Palaidiet servisus

Jums būs jāpalaiž Lietotāju serviss un Produktu serviss dažādos portos. Piemēram:

Lietotāju serviss (ports 4001):


const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { schema, rootValue } = require('./user-service');

const app = express();
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: rootValue,
  graphiql: true,
}));

app.listen(4001, () => console.log('Lietotāju serviss darbojas http://localhost:4001/graphql'));

Produktu serviss (ports 4002):


const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { schema, rootValue } = require('./product-service');

const app = express();
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: rootValue,
  graphiql: true,
}));

app.listen(4002, () => console.log('Produktu serviss darbojas http://localhost:4002/graphql'));

4. Vaicājiet savienoto shēmu

Tagad jūs varat vaicāt savienoto shēmu caur vārteju (kas darbojas 4000. portā). Jūs varat izpildīt šādu vaicājumu:


query {
  product(id: "101") {
    id
    name
    price
    user {
      id
      name
      email
    }
  }
}

Šis vaicājums iegūst produktu ar ID "101" un arī saņem saistīto lietotāju no Lietotāju servisa, demonstrējot, kā shēmu savienošana ļauj jums vaicāt datus no vairākiem servisiem vienā pieprasījumā.

Papildu shēmu savienošanas metodes

Papildus pamata piemēram, šeit ir dažas papildu metodes, kuras var izmantot, lai uzlabotu jūsu shēmu savienošanas ieviešanu:

Izvēle starp shēmu savienošanu un Apollo federāciju

Lai gan shēmu savienošana ir dzīvotspējīgs variants GraphQL federācijai, Apollo federācija ir kļuvusi par populārāku izvēli, pateicoties tās papildu funkcijām un uzlabotajai izstrādātāju pieredzei. Šeit ir abu pieeju salīdzinājums:

Funkcija Shēmu savienošana Apollo federācija
Shēmas definīcija Izmanto esošo GraphQL shēmas valodu Izmanto deklaratīvu shēmas valodu ar direktīvām
Vaicājumu plānošana Nepieciešama manuāla vaicājumu deleģēšana Automātiska vaicājumu plānošana ar Apollo vārteju
Tipu paplašinājumi Ierobežots atbalsts Iebūvēts atbalsts tipu paplašinājumiem
Atslēgu direktīvas Netiek atbalstīts Izmanto @key direktīvu, lai identificētu entītijas
Izkliedētā trasēšana Nepieciešama manuāla ieviešana Iebūvēts atbalsts izkliedētai trasēšanai
Rīki un ekosistēma Mazāk nobrieduši rīki Nobriedušāki rīki un liela kopiena
Sarežģītība Var būt sarežģīti pārvaldīt lielās sistēmās Paredzēta lielām un sarežģītām sistēmām

Kad izvēlēties shēmu savienošanu:

Kad izvēlēties Apollo federāciju:

Reālās pasaules piemēri un lietošanas gadījumi

Šeit ir daži reālās pasaules piemēri, kā var izmantot GraphQL federāciju, ieskaitot shēmu savienošanu:

Labākās prakses shēmu savienošanai

Lai nodrošinātu veiksmīgu shēmu savienošanas ieviešanu, ievērojiet šīs labākās prakses:

Noslēgums

GraphQL federācija ar shēmu savienošanu piedāvā jaudīgu pieeju, lai veidotu vienotas API no vairākiem servisiem mikroservisu arhitektūrā. Izprotot tās pamatjēdzienus, priekšrocības, ierobežojumus un ieviešanas metodes, jūs varat izmantot shēmu savienošanu, lai vienkāršotu datu piekļuvi, uzlabotu mērogojamību un veicinātu uzturēšanu. Lai gan Apollo federācija ir kļuvusi par modernāku risinājumu, shēmu savienošana joprojām ir dzīvotspējīgs variants vienkāršākiem scenārijiem vai integrējot esošus GraphQL servisus. Rūpīgi apsveriet savas īpašās vajadzības un prasības, lai izvēlētos labāko pieeju jūsu organizācijai.